package com.zb.kc.acl.helper;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Sets;
import com.zb.kc.acl.entity.Permission;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 根据权限数据构建登录用户左侧菜单数据
 * </p>
 *
 * @author qy
 * @since 2019-11-11
 */
public class MenuHelper {

    /**
     * 构建菜单树形结构
     *
     * @param realMenu
     * @return
     */
    public static Permission buildMenuTree(List<Permission> realMenu) {
        // 过滤到不用的菜单
        List<Permission> allMenu = realMenu.stream().filter(m -> !StringUtils.isEmpty(m.getComponent())).collect(Collectors.toList());
        // 获取根节点
        Optional<Permission> first = allMenu.stream().filter(m -> "1".equals(m.getId())).findFirst();
        Permission rootMenu = first.isPresent() ? first.get() : null;
        // 如果根节点为空则初始化根节点
        if (ObjectUtil.isNull(rootMenu)) {
            rootMenu = new Permission();
            rootMenu.setId("1");
            rootMenu.setPid("0");
            rootMenu.setName("全部数据");
            rootMenu.setType(0);
            rootMenu.setIsDeleted(false);
            rootMenu.setSelect(false);
        }
        rootMenu.setLevel(0);
        // 过滤获取所有1级菜单
        List<Permission> oneLevelMenu = allMenu.stream().filter(m -> "1".equals(m.getPid())).collect(Collectors.toList());
        Set<String> menuIds = Sets.newHashSetWithExpectedSize(allMenu.size());
        oneLevelMenu.forEach(m -> getChildrenMenu(m, allMenu, menuIds, 0));
        rootMenu.setChildren(oneLevelMenu);
        return rootMenu;
    }

    public static List<JSONObject> buildJson(Permission rootMenu) {
        // 获取一级菜单列表
        List<Permission> oneLevel = rootMenu.getChildren();
        // 递归构建菜单json树
        List<JSONObject> menus = buildMenuJsonTree(oneLevel);
        return menus;
    }

    private static List<JSONObject> buildMenuJsonTree(List<Permission> childrenMenus) {
        List<JSONObject> meuns = new ArrayList<>();
        for (Permission one : childrenMenus) {
            JSONObject oneMeun = new JSONObject();
            oneMeun.put("path", one.getPath());
            oneMeun.put("component", one.getComponent());
            oneMeun.put("redirect", "noredirect");
            oneMeun.put("name", "name_" + one.getId());
            oneMeun.put("hidden", false);

            JSONObject oneMeta = new JSONObject();
            oneMeta.put("title", one.getName());
            oneMeta.put("icon", one.getIcon());
            oneMeun.put("meta", oneMeta);

            List<JSONObject> children = new ArrayList<>();
            List<Permission> twoMeunList = one.getChildren();
            for (Permission two : twoMeunList) {
                JSONObject twoMeun = new JSONObject();
                twoMeun.put("path", two.getPath());
                twoMeun.put("component", two.getComponent());
                twoMeun.put("name", "name_" + two.getId());
                twoMeun.put("hidden", false);

                JSONObject twoMeta = new JSONObject();
                twoMeta.put("title", two.getName());
                twoMeun.put("meta", twoMeta);

                children.add(twoMeun);

                List<Permission> threeMeunList = two.getChildren();
                for (Permission three : threeMeunList) {
                    if (StringUtils.isEmpty(three.getPath())) continue;

                    JSONObject threeMeun = new JSONObject();
                    threeMeun.put("path", three.getPath());
                    threeMeun.put("component", three.getComponent());
                    threeMeun.put("name", "name_" + three.getId());
                    threeMeun.put("hidden", true);

                    JSONObject threeMeta = new JSONObject();
                    threeMeta.put("title", three.getName());
                    threeMeun.put("meta", threeMeta);

                    children.add(threeMeun);
                }
            }
            oneMeun.put("children", children);
            meuns.add(oneMeun);
        }
        return meuns;
    }

    /**
     * 递归的获取子节点
     * <p>
     * level: 自定义的节点级别，也指递归深度
     *
     * @param parentNode
     * @return
     */
    private static void getChildrenMenu(Permission parentNode, List<Permission> allMenu, Set<String> menuIds, int level) {
        List<Permission> children = new ArrayList<>();
        int finalLevel = level + 1;
        allMenu.stream()
                .filter(m -> !menuIds.contains(m.getId()))
                .filter(m -> parentNode.getId().equals(m.getPid())) // 过滤获取父节点的子节点们
                .forEach(m -> {
                    getChildrenMenu(m, allMenu, menuIds, finalLevel);
                    menuIds.add(m.getId());
                    children.add(m);
                });
        parentNode.setLevel(finalLevel);
        parentNode.setChildren(children);
    }
}
